namespace Atom.Utility.Data
{
    using System;
    using System.Configuration;
    using System.Data;
    using System.Data.Common;
    using System.Data.SqlClient;
    using System.Globalization;
    using System.Runtime.CompilerServices;
    using System.Transactions;

    public class Database
    {
        [CompilerGenerated]
        private System.Configuration.ConnectionStringSettings k__BackingField;
        private DbProviderFactory dbProviderFactory;
        private static ParameterCache parameterCache = new ParameterCache();

        internal Database(System.Configuration.ConnectionStringSettings connectionStringSettings)
        {
            this.ConnectionStringSettings = connectionStringSettings;
        }

        public void AddInParameter(DbCommand command, string name, DbType dbType)
        {
            this.AddParameter(command, name, dbType, ParameterDirection.Input, string.Empty, DataRowVersion.Default, null);
        }

        public void AddInParameter(DbCommand command, string name, DbType dbType, object value)
        {
            this.AddParameter(command, name, dbType, ParameterDirection.Input, string.Empty, DataRowVersion.Default, value);
        }

        public void AddInParameter(DbCommand command, string name, DbType dbType, string sourceColumn, DataRowVersion sourceVersion)
        {
            this.AddParameter(command, name, dbType, 0, ParameterDirection.Input, true, 0, 0, sourceColumn, sourceVersion, null);
        }

        public void AddOutParameter(DbCommand command, string name, DbType dbType, int size)
        {
            this.AddParameter(command, name, dbType, size, ParameterDirection.Output, true, 0, 0, string.Empty, DataRowVersion.Default, DBNull.Value);
        }

        public void AddParameter(DbCommand command, string name, DbType dbType, ParameterDirection direction, string sourceColumn, DataRowVersion sourceVersion, object value)
        {
            this.AddParameter(command, name, dbType, 0, direction, false, 0, 0, sourceColumn, sourceVersion, value);
        }

        public virtual void AddParameter(DbCommand command, string name, DbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
        {
            DbParameter parameter = this.CreateParameter(name, dbType, size, direction, nullable, precision, scale, sourceColumn, sourceVersion, value);
            command.Parameters.Add(parameter);
        }

        private void AssignParameterValues(DbCommand command, object[] values)
        {
            int num = this.UserParametersStartIndex();
            for (int i = 0; i < values.Length; i++)
            {
                IDataParameter parameter = command.Parameters[i + num];
                this.SetParameterValue(command, parameter.ParameterName, values[i]);
            }
        }

        private DbTransaction BeginTransaction(DbConnection connection)
        {
            return connection.BeginTransaction();
        }

        public virtual string BuildParameterName(string name)
        {
            return name;
        }

        public static void ClearParameterCache()
        {
            parameterCache.Clear();
        }

        private void CommitTransaction(DbTransaction tran)
        {
            tran.Commit();
        }

        protected virtual void ConfigureParameter(DbParameter param, string name, DbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
        {
            param.DbType = dbType;
            param.Size = size;
            param.Value = (value == null) ? DBNull.Value : value;
            param.Direction = direction;
            param.IsNullable = nullable;
            param.SourceColumn = sourceColumn;
            param.SourceVersion = sourceVersion;
        }

        private DbCommand CreateCommandByCommandType(CommandType commandType, string commandText)
        {
            DbCommand command = this.Factory.CreateCommand();
            command.CommandType = commandType;
            command.CommandText = commandText;
            return command;
        }

        public virtual DbConnection CreateConnection()
        {
            DbConnection connection = this.Factory.CreateConnection();
            connection.ConnectionString = this.ConnectionStringSettings.ConnectionString;
            return connection;
        }

        protected DbParameter CreateParameter(string name)
        {
            DbParameter parameter = this.Factory.CreateParameter();
            parameter.ParameterName = this.BuildParameterName(name);
            return parameter;
        }

        protected DbParameter CreateParameter(string name, DbType dbType, int size, ParameterDirection direction, bool nullable, byte precision, byte scale, string sourceColumn, DataRowVersion sourceVersion, object value)
        {
            DbParameter param = this.CreateParameter(name);
            this.ConfigureParameter(param, name, dbType, size, direction, nullable, precision, scale, sourceColumn, sourceVersion, value);
            return param;
        }

        protected virtual void DeriveParameters(DbCommand discoveryCommand)
        {
            SqlCommandBuilder.DeriveParameters((SqlCommand) discoveryCommand);
        }

        public void DiscoverParameters(DbCommand command)
        {
            using (ConnectionWrapper wrapper = this.GetOpenConnection())
            {
                using (DbCommand command2 = this.CreateCommandByCommandType(command.CommandType, command.CommandText))
                {
                    command2.Connection = wrapper.Connection;
                    this.DeriveParameters(command2);
                    command2.Parameters.RemoveAt(0);
                    foreach (IDataParameter parameter in command2.Parameters)
                    {
                        IDataParameter parameter2 = (IDataParameter) ((ICloneable) parameter).Clone();
                        command.Parameters.Add(parameter2);
                    }
                }
            }
        }

        protected int DoExecuteNonQuery(DbCommand command)
        {
            int num2;
            try
            {
                DateTime now = DateTime.Now;
                num2 = command.ExecuteNonQuery();
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return num2;
        }

        private IDataReader DoExecuteReader(DbCommand command, CommandBehavior cmdBehavior)
        {
            IDataReader reader2;
            try
            {
                DateTime now = DateTime.Now;
                reader2 = command.ExecuteReader(cmdBehavior);
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return reader2;
        }

        private object DoExecuteScalar(DbCommand command)
        {
            object obj3;
            try
            {
                DateTime now = DateTime.Now;
                obj3 = command.ExecuteScalar();
            }
            catch (Exception exception)
            {
                throw exception;
            }
            return obj3;
        }

        public virtual DataSet ExecuteDataSet(DbCommand command)
        {
            DataSet dataSet = new DataSet();
            dataSet.Locale = CultureInfo.InvariantCulture;
            using (DbConnection connection = this.CreateConnection())
            {
                command.Connection = connection;
                DbDataAdapter adapter = this.Factory.CreateDataAdapter();
                adapter.SelectCommand = command;
                adapter.Fill(dataSet, "Table");
            }
            return dataSet;
        }

        public virtual DataSet ExecuteDataSet(CommandType commandType, string commandText)
        {
            using (DbCommand command = this.CreateCommandByCommandType(commandType, commandText))
            {
                return this.ExecuteDataSet(command);
            }
        }

        public virtual DataSet ExecuteDataSet(DbCommand command, DbTransaction transaction)
        {
            DataSet dataSet = new DataSet();
            dataSet.Locale = CultureInfo.InvariantCulture;
            using (DbConnection connection = this.CreateConnection())
            {
                command.Connection = connection;
                DbDataAdapter adapter = this.Factory.CreateDataAdapter();
                adapter.SelectCommand = command;
                adapter.Fill(dataSet, "Table");
            }
            return dataSet;
        }

        public virtual DataSet ExecuteDataSet(string storedProcedureName, params object[] parameterValues)
        {
            using (DbCommand command = this.GetStoredProcCommand(storedProcedureName, parameterValues))
            {
                return this.ExecuteDataSet(command);
            }
        }

        public virtual DataSet ExecuteDataSet(DbTransaction transaction, CommandType commandType, string commandText)
        {
            using (DbCommand command = this.CreateCommandByCommandType(commandType, commandText))
            {
                return this.ExecuteDataSet(command, transaction);
            }
        }

        public virtual DataSet ExecuteDataSet(DbTransaction transaction, string storedProcedureName, params object[] parameterValues)
        {
            using (DbCommand command = this.GetStoredProcCommand(storedProcedureName, parameterValues))
            {
                return this.ExecuteDataSet(command, transaction);
            }
        }

        public virtual int ExecuteNonQuery(DbCommand command)
        {
            using (ConnectionWrapper wrapper = this.GetOpenConnection())
            {
                PrepareCommand(command, wrapper.Connection);
                return this.DoExecuteNonQuery(command);
            }
        }

        public virtual int ExecuteNonQuery(CommandType commandType, string commandText)
        {
            using (DbCommand command = this.CreateCommandByCommandType(commandType, commandText))
            {
                return this.ExecuteNonQuery(command);
            }
        }

        public virtual int ExecuteNonQuery(DbCommand command, DbTransaction transaction)
        {
            PrepareCommand(command, transaction);
            return this.DoExecuteNonQuery(command);
        }

        public virtual int ExecuteNonQuery(string storedProcedureName, params object[] parameterValues)
        {
            using (DbCommand command = this.GetStoredProcCommand(storedProcedureName, parameterValues))
            {
                return this.ExecuteNonQuery(command);
            }
        }

        public virtual int ExecuteNonQuery(DbTransaction transaction, CommandType commandType, string commandText)
        {
            using (DbCommand command = this.CreateCommandByCommandType(commandType, commandText))
            {
                return this.ExecuteNonQuery(command, transaction);
            }
        }

        public virtual int ExecuteNonQuery(DbTransaction transaction, string storedProcedureName, params object[] parameterValues)
        {
            using (DbCommand command = this.GetStoredProcCommand(storedProcedureName, parameterValues))
            {
                return this.ExecuteNonQuery(command, transaction);
            }
        }

        public virtual IDataReader ExecuteReader(DbCommand command)
        {
            IDataReader reader;
            ConnectionWrapper openConnection = this.GetOpenConnection(false);
            try
            {
                PrepareCommand(command, openConnection.Connection);
                if (Transaction.Current != null)
                {
                    return this.DoExecuteReader(command, CommandBehavior.Default);
                }
                reader = this.DoExecuteReader(command, CommandBehavior.CloseConnection);
            }
            catch
            {
                openConnection.Connection.Close();
                throw;
            }
            return reader;
        }

        public IDataReader ExecuteReader(CommandType commandType, string commandText)
        {
            using (DbCommand command = this.CreateCommandByCommandType(commandType, commandText))
            {
                return this.ExecuteReader(command);
            }
        }

        public virtual IDataReader ExecuteReader(DbCommand command, DbTransaction transaction)
        {
            PrepareCommand(command, transaction);
            return this.DoExecuteReader(command, CommandBehavior.Default);
        }

        public IDataReader ExecuteReader(string storedProcedureName, params object[] parameterValues)
        {
            using (DbCommand command = this.GetStoredProcCommand(storedProcedureName, parameterValues))
            {
                return this.ExecuteReader(command);
            }
        }

        public IDataReader ExecuteReader(DbTransaction transaction, CommandType commandType, string commandText)
        {
            using (DbCommand command = this.CreateCommandByCommandType(commandType, commandText))
            {
                return this.ExecuteReader(command, transaction);
            }
        }

        public IDataReader ExecuteReader(DbTransaction transaction, string storedProcedureName, params object[] parameterValues)
        {
            using (DbCommand command = this.GetStoredProcCommand(storedProcedureName, parameterValues))
            {
                return this.ExecuteReader(command, transaction);
            }
        }

        public virtual object ExecuteScalar(DbCommand command)
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }
            using (ConnectionWrapper wrapper = this.GetOpenConnection())
            {
                PrepareCommand(command, wrapper.Connection);
                return this.DoExecuteScalar(command);
            }
        }

        public virtual object ExecuteScalar(CommandType commandType, string commandText)
        {
            using (DbCommand command = this.CreateCommandByCommandType(commandType, commandText))
            {
                return this.ExecuteScalar(command);
            }
        }

        public virtual object ExecuteScalar(DbCommand command, DbTransaction transaction)
        {
            PrepareCommand(command, transaction);
            return this.DoExecuteScalar(command);
        }

        public virtual object ExecuteScalar(string storedProcedureName, params object[] parameterValues)
        {
            using (DbCommand command = this.GetStoredProcCommand(storedProcedureName, parameterValues))
            {
                return this.ExecuteScalar(command);
            }
        }

        public virtual object ExecuteScalar(DbTransaction transaction, CommandType commandType, string commandText)
        {
            using (DbCommand command = this.CreateCommandByCommandType(commandType, commandText))
            {
                return this.ExecuteScalar(command, transaction);
            }
        }

        public virtual object ExecuteScalar(DbTransaction transaction, string storedProcedureName, params object[] parameterValues)
        {
            using (DbCommand command = this.GetStoredProcCommand(storedProcedureName, parameterValues))
            {
                return this.ExecuteScalar(command, transaction);
            }
        }

        internal DbConnection GetNewOpenConnection()
        {
            DbConnection connection = null;
            try
            {
                try
                {
                    connection = this.CreateConnection();
                    connection.Open();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
            }
            catch
            {
                if (connection != null)
                {
                    connection.Close();
                }
                throw;
            }
            return connection;
        }

        protected ConnectionWrapper GetOpenConnection()
        {
            return this.GetOpenConnection(true);
        }

        protected ConnectionWrapper GetOpenConnection(bool disposeInnerConnection)
        {
            DbConnection connection = TransactionScopeConnections.GetConnection(this);
            if (connection != null)
            {
                return new ConnectionWrapper(connection, false);
            }
            return new ConnectionWrapper(this.GetNewOpenConnection(), disposeInnerConnection);
        }

        public virtual object GetParameterValue(DbCommand command, string name)
        {
            return command.Parameters[this.BuildParameterName(name)].Value;
        }

        public DbCommand GetSqlStringCommand(string query)
        {
            if (string.IsNullOrEmpty(query))
            {
                throw new ArgumentException("不能为空", "query");
            }
            return this.CreateCommandByCommandType(CommandType.Text, query);
        }

        public virtual DbCommand GetStoredProcCommand(string storedProcedureName)
        {
            if (string.IsNullOrEmpty(storedProcedureName))
            {
                throw new ArgumentException("不能为空", "storedProcedureName");
            }
            return this.CreateCommandByCommandType(CommandType.StoredProcedure, storedProcedureName);
        }

        public virtual DbCommand GetStoredProcCommand(string storedProcedureName, params object[] parameterValues)
        {
            if (string.IsNullOrEmpty(storedProcedureName))
            {
                throw new ArgumentException("不能为空", "storedProcedureName");
            }
            DbCommand command = this.CreateCommandByCommandType(CommandType.StoredProcedure, storedProcedureName);
            parameterCache.SetParameters(command, this);
            if (!this.SameNumberOfParametersAndValues(command, parameterValues))
            {
                throw new InvalidOperationException("参数对应错误");
            }
            this.AssignParameterValues(command, parameterValues);
            return command;
        }

        [Obsolete("Use GetOpenConnection instead.")]
        protected DbConnection OpenConnection()
        {
            return this.GetNewOpenConnection();
        }

        protected static void PrepareCommand(DbCommand command, DbConnection connection)
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }
            command.Connection = connection;
        }

        protected static void PrepareCommand(DbCommand command, DbTransaction transaction)
        {
            if (command == null)
            {
                throw new ArgumentNullException("command");
            }
            if (transaction == null)
            {
                throw new ArgumentNullException("transaction");
            }
            PrepareCommand(command, transaction.Connection);
            command.Transaction = transaction;
        }

        private void RollbackTransaction(DbTransaction tran)
        {
            tran.Rollback();
        }

        protected virtual bool SameNumberOfParametersAndValues(DbCommand command, object[] values)
        {
            int count = command.Parameters.Count;
            int length = values.Length;
            return (count == length);
        }

        public virtual void SetParameterValue(DbCommand command, string parameterName, object value)
        {
            command.Parameters[this.BuildParameterName(parameterName)].Value = (value == null) ? DBNull.Value : value;
        }

        protected virtual int UserParametersStartIndex()
        {
            return 0;
        }

        public string ConnectionString
        {
            get
            {
                return this.ConnectionStringSettings.ConnectionString;
            }
        }

        public System.Configuration.ConnectionStringSettings ConnectionStringSettings
        {
            [CompilerGenerated]
            get
            {
                return this.k__BackingField;
            }
            [CompilerGenerated]
            private set
            {
                this.k__BackingField = value;
            }
        }

        public DbProviderFactory Factory
        {
            get
            {
                if (this.dbProviderFactory == null)
                {
                    this.dbProviderFactory = DbProviderFactories.GetFactory(this.ConnectionStringSettings.ProviderName);
                }
                return this.dbProviderFactory;
            }
        }

        protected class ConnectionWrapper : IDisposable
        {
            private DbConnection connection;
            private bool disposeConnection;

            public ConnectionWrapper(DbConnection connection, bool disposeConnection)
            {
                this.connection = connection;
                this.disposeConnection = disposeConnection;
            }

            public void Dispose()
            {
                if (this.disposeConnection)
                {
                    this.connection.Dispose();
                }
            }

            public DbConnection Connection
            {
                get
                {
                    return this.connection;
                }
            }
        }
    }
}
